package com.dubbo.common.security;

import com.dubbo.common.SerializeUtil;
import com.dubbo.common.exception.UserExpiredException;
import com.dubbo.common.redis.RedisDao;
import com.dubbo.common.security.bean.UserBean;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.auth.AuthenticationException;
//import org.apache.shiro.authc.ExpiredCredentialsException;
//import org.apache.shiro.authz.AuthorizationException;

import java.util.List;


/**
 * 权限认证工具
 * @author chenwei
 * @date 2018年12月5日 下午2:28:31
 */
public interface SecurityUtils {
	
	
	/**
	 * 添加用户数据
	 * 
	 * @author chenwei
	 * @date 2018年12月5日 下午3:16:51
	 * @param redisDao redis客户端
	 * @param key 保存用户数据的key (token)
	 * @param userBean 用户数据
	 * @param seconds 数据存储的声明周期秒
	 * @throws Exception
	 */
	public static void addUserBean(
            RedisDao redisDao,
            String key,
            UserBean userBean,
            long seconds) throws Exception {
		redisDao.add(key, seconds, SerializeUtil.serialize(userBean));
	}
	
	/**
	 * 获取用户实体类
	 * 
	 * @author chenwei
	 * @date 2018年12月5日 下午2:48:59
	 * @param redisDao redis客户端对象
	 * @param token 用户token(reids的key)
	 * @return
	 * @throws Exception 
	 */
	public static Object getUserBean(RedisDao redisDao, String token) throws Exception {
		checkRedisObject(redisDao);
		checkUserKsy(token);
		Object userObject = SerializeUtil
				.deserialize(redisDao.getByte(token));
		checkUserBean(userObject);
		UserBean user = (UserBean)userObject;
		return user.getUserObj();
	}
	
	/**
	 * 校验角色
	 * 
	 * @author chenwei
	 * @date 2018年12月5日 下午3:28:40
	 * @param role 角色名称
	 * @param redisDao reids客户端
	 * @param token 用户token
	 * @throws Exception
	 */
	public static void checkRole(String role, RedisDao redisDao, String token) throws Exception{
//		UserBean userBean = (UserBean) getUserBean(redisDao, token);
		UserBean userBean = (UserBean) getUserBean2(redisDao, token);
		List<String> roles = userBean.getRoles();
		checkRoleOrPermissionExecute(role, roles);
	}
	/**
	 * 校验角色
	 * 
	 * @author chenwei
	 * @date 2018年12月5日 下午3:33:26
	 * @param role 角色名称
	 * @param roles 用户存储的角色数据
	 * @throws Exception
	 */
	public static void checkRole(String role, List<String> roles) throws Exception{
		checkRoleOrPermissionExecute(role, roles);
	}
	
	/**
	 * 校验权限
	 * 
	 * @author chenwei
	 * @date 2018年12月5日 下午3:38:00
	 * @param permission 权限名称
	 * @param redisDao reids客户端
	 * @param token 用户token
	 * @throws Exception
	 */
	public static void checkPermission(
            String permission,
            RedisDao redisDao,
            String token) throws Exception {
//		UserBean userBean = (UserBean) getUserBean(redisDao, token);
		UserBean userBean = (UserBean) getUserBean2(redisDao, token);
		checkRoleOrPermissionExecute(
				permission,  
//				userBean.getRoles()
				userBean.getPermissions()
				);
	}
	/**
	 * 校验权限
	 * 
	 * @author chenwei
	 * @date 2018年12月5日 下午3:33:26
	 * @param permission 权限名称
	 * @param permissions 用户存储的权限数据
	 * @throws Exception
	 */
	public static void checkPermission(String permission, List<String> permissions) throws Exception{
		checkRoleOrPermissionExecute(permission, permissions);
	}

	static void checkRoleOrPermissionExecute(
            String roleOrPermission,
            List<String> roleOrPermissions) throws AuthenticationException {
		if(!StringUtils.isNotBlank(roleOrPermission)) {
			throw new AuthenticationException();
		}
		if(roleOrPermission == null || roleOrPermissions.isEmpty()) {
			throw new AuthenticationException();
		}
		if(!roleOrPermissions.contains(roleOrPermission)) {
			throw new AuthenticationException();
		}
	}
	
	/**
	 * 校验用户实体
	 * 
	 * @author chenwei
	 * @date 2018年12月5日 下午2:56:15
	 * @param userObject
	 */
	static void checkUserBean(Object userObject) throws UserExpiredException {
		if(userObject == null) {
			throw new UserExpiredException("登录失效~");
		}
	}
	/**
	 * 校验redisClient
	 * 
	 * @author chenwei
	 * @date 2018年12月5日 下午2:47:35
	 * @param redisDao
	 */
	static void checkRedisObject(RedisDao redisClient) {
		if(redisClient == null) {
			throw new NullPointerException("redis客户端对象为null~");
		}
	}
	/**
	 * 校验用户token
	 * 
	 * @author chenwei
	 * @date 2018年12月5日 下午2:47:02
	 * @param userKsy
	 */
	static void checkUserKsy(String token) {
		if(!StringUtils.isNotBlank(token)) {
			throw new NullPointerException("用户token不能为空~");
		}
	}
	
	/**
	 * (内部用)获取UserBean
	 * @author chenluqiang
	 * @date 2018年12月14日 下午4:21:35 
	 * @param redisDao
	 * 
	 * @param token
	 * @return
	 * @throws Exception
	 */
	static Object getUserBean2(RedisDao redisDao, String token) throws Exception {
		checkRedisObject(redisDao);
		checkUserKsy(token);
		Object userObject = SerializeUtil
				.deserialize(redisDao.getByte(token));
		checkUserBean(userObject);
		UserBean user = (UserBean)userObject;
		return user;
	}
}
